package com.kamistoat.meimeimall.meimeimallseckill.controller;

import com.kamistoat.meimeimall.common.utils.PageUtils;
import com.kamistoat.meimeimall.common.utils.Query;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//import org.apache.shiro.authz.annotation.RequiresPermissions;
import com.kamistoat.meimeimall.common.annotation.DubboAndHTTPExceptionCatch;
import com.kamistoat.meimeimall.common.annotation.LoginRequired;
import com.kamistoat.meimeimall.common.constant.SecKillConstant;
import com.kamistoat.meimeimall.common.dubboInterface.SecKillDubboInterface;
import com.kamistoat.meimeimall.meimeimallseckill.entity.SeckillSessionEntity;
import com.kamistoat.meimeimall.meimeimallseckill.service.SeckillSessionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import com.kamistoat.meimeimall.common.utils.R;


/**
 * 秒杀活动场次
 *
 * @author kamistoat
 * @email linjianshanke@163.com
 * @date 2021-09-12 16:19:46
 */
@Api(tags="秒杀活动场次数据库操作")
@RestController
@RequestMapping("seckillsession")
public class SeckillSessionController {

    protected Logger logger = LoggerFactory.getLogger(SeckillSessionController.class);

    @Autowired
    SeckillSessionService seckillSessionService;

    @Reference
    SecKillDubboInterface secKillDubboInterface;

    /**
     * 列表
     */
    @ApiOperation("从数据库获取列表")
    @GetMapping("/list")
    @LoginRequired
    @DubboAndHTTPExceptionCatch
    public R list(@RequestParam Map<String, Object> params) {
        PageUtils page = seckillSessionService.queryPage(params);

        return R.ok().put("page", page);
    }


    /**
     * 信息
     */
    @ApiOperation("从数据库查询指定的POJO")
    @GetMapping("/seckill_session_info")
    @LoginRequired
    @DubboAndHTTPExceptionCatch
    public R info(@RequestParam("id") Long id) {
        SeckillSessionEntity seckillSession = seckillSessionService.getById(id);

        return R.ok().put("seckillSession", seckillSession);
    }

    /**
     * 当管理系统添加秒杀场次时，除了进MySQL，还检查该秒杀是否位于3天以内，如果是，同时在redis进行缓存。
     */
    @ApiOperation("向数据库保存POJO")
    @PutMapping("/seckill_session_info")
    @LoginRequired
    @DubboAndHTTPExceptionCatch
    public R save(@RequestBody SeckillSessionEntity seckillSession) {
        R status = seckillSessionService.checkSeckillSession(seckillSession);
        if ((int) status.get("code") == 0) {
            seckillSessionService.save(seckillSession);
            // 已弃用。Feign调用
            // secKillFeignService.delete_ReUp_RedisSessions(getRedisSessionKey(new Long[]{seckillSession.getId()}));

            // Dubbo调用
            R resultR = secKillDubboInterface.deleteAndReUpToRedis(getRedisSessionKey(new Long[]{seckillSession.getId()}));
            if (resultR.getCode() != 0) {
                logger.error(resultR.getMsg());
            }
            return resultR;
        } else {
            return status;
        }
    }

    /**
     * 当管理系统修改秒杀场次时，除了进MySQL，还检查该秒杀是否位于3天以内，如果是，同时在redis删除旧缓存，缓存新秒杀。
     */
    @ApiOperation("向数据库更新POJO")
    @PostMapping("/seckill_session_info")
    @LoginRequired
    @DubboAndHTTPExceptionCatch
    public R update(@RequestBody SeckillSessionEntity seckillSession) {
        R status = seckillSessionService.checkSeckillSession(seckillSession);
        if ((int) status.get("code") == 0) {
            seckillSessionService.updateById(seckillSession);
            // secKillFeignService.delete_ReUp_RedisSessions(getRedisSessionKey(new Long[]{seckillSession.getId()}));

            R resultR = secKillDubboInterface.deleteAndReUpToRedis(getRedisSessionKey(new Long[]{seckillSession.getId()}));
            if (resultR.getCode() != 0) {
                logger.error(resultR.getMsg());
            }
            return resultR;
        } else {
            return status;
        }
    }

    /**
     * 删除某一场秒杀活动，删除的同时还要检查redis中是否存在已上架的秒杀活动。如果存在则需要将其一并删除
     */
    @ApiOperation("从数据库删除指定POJO")
    @DeleteMapping("/seckill_session_info")
    @LoginRequired
    @DubboAndHTTPExceptionCatch
    public R delete(@RequestBody Long[] ids) {
        List<String> redisSessionKey = getRedisSessionKey(ids);
        seckillSessionService.removeByIds(Arrays.asList(ids));
        // secKillFeignService.delete_ReUp_RedisSessions(redisSessionKey);

        R resultR = secKillDubboInterface.deleteAndReUpToRedis(redisSessionKey);
        if (resultR.getCode() != 0) {
            logger.error(resultR.getMsg());
        }

        return resultR;
    }

    /**
     * 根据ids制作redis keyList
     *
     * @param ids
     * @return
     */
    public List<String> getRedisSessionKey(Long[] ids) {
        return seckillSessionService.listByIds(Arrays.asList(ids)).stream().map(seckillSessionEntity -> {
            String key = SecKillConstant.SEC_SESSION_PREFIX
                    + seckillSessionEntity.getStartTime().getTime() + "_" + seckillSessionEntity.getEndTime().getTime();
            return key;
        }).collect(Collectors.toList());
    }

}
